import random
import time

import requests
import xmltodict
from django.conf import settings
from django.http import HttpResponse
from libs.utils import ajax, db
from .wxpay_config import WxPayConfig

notify_url = settings.ROOT_URL

def native(request):
    """
          功能:微信支付——扫一扫支付
          -----------------------------------------------
          添加人:王*
          -----------------------------------------------
          添加时间:2019-7-12
          -----------------------------------------------
          @api {post} /wechat/native/ [微信支付]微信支付——扫一扫支付
          @apiGroup area
          @apiSuccessExample {json} 成功返回
              {
                  "message": "",
                  "next": "",
                  "data": {
                  "order_no":order_no, #我们的支付订单号
                  "code_url":code_url,#字符串二维码
                  "goods_name":goods_name, #商品名称
                  "price":0.01, #价格
                  },
                  "response": "ok",
                  "error": ""
              }
          @apiSuccess {str} order_no      我们的支付订单号
          @apiSuccess {str} code_url       字符串二维码
          @apiSuccess {str} goods_name    商品名称
          @apiSuccess {str} price           价格
          @apiErrorExample {json} 失败返回
              {
                  "message": "缺少参数",
                  "next": "",
                  "data": {
                      "order_no":order_no, #我们的支付订单号
                      "code_url":"",#字符串二维码
                      "goods_name":goods_name, #商品名称
                      "price":0.01, #价格
                  },
                  "response": "ok",
                  "error": ""
              }
          """
    args = request.QUERY.casts(config_id=int,goods_id=int)
    config_id = args.config_id
    goods_id = args.goods_id
    if not config_id or not goods_id:
        return ajax.jsonp_fail(request, message="支付参数不合法")
    ip = get_client_ip(request).split(",")[0]
    order_no = WxPayConfig.create_trade_no()
    goods_config_db=get_goods_config(config_id,goods_id)
    if goods_config_db:
        goods_name = goods_config_db.name
        price=float(goods_config_db.price)
    else:
        return ajax.jsonp_fail(request,message="商品信息不合法")
    wxpay_class = WxPayConfig(body=goods_name, price=price, res_ip=ip, notify_url=notify_url, order_no=order_no,config_id=config_id)
    code_url = ""
    trade_type = "NATIVE"
    res, error = wxpay_class.payExecute(trade_type)
    if res:
        code_url = res.code_url
        pay_info_add(order_no, goods_name, 1)
    data = {"order_no": order_no, "code_url": code_url, "goods_name": goods_name, "price": price}

    return ajax.jsonp_ok(request, data=data)


def mweb(request):
    """
      功能:微信支付——H5支付
      -----------------------------------------------
      添加人:王*
      -----------------------------------------------
      添加时间:2019-7-12
      -----------------------------------------------
      @api {post} /wechat/mweb/ [微信支付]微信支付——H5支付
      @apiGroup area
      @apiSuccessExample {json} 成功返回
          {
              "message": "",
              "next": "",
              "data": {
                    "order_no":order_no, #我们的支付订单号
                "   mweb_url":"111",#支付跳转url，前端重新跳转到这个url中
              },
              "response": "ok",
              "error": ""
          }
      @apiSuccess {str} order_no      我们的支付订单号
      @apiSuccess {str} mweb_url       支付跳转url，前端重新跳转到这个url中
      @apiErrorExample {json} 失败返回
          {
              "message": "缺少参数",
              "next": "",
              "data": {
                  "order_no":order_no, #我们的支付订单号
                  "mweb_url":"",#支付跳转url，前端重新跳转到这个url中
              },
              "response": "ok",
              "error": ""
          }
      """
    args = request.QUERY.casts(config_id=int,goods_id=int)
    config_id = args.config_id
    goods_id = args.goods_id
    if not config_id or not goods_id:
        return ajax.jsonp_fail(request, message="支付参数不合法")
    ip = get_client_ip(request).split(",")[0]
    order_no = WxPayConfig.create_trade_no()
    goods_config_db = get_goods_config(config_id,goods_id)
    if goods_config_db:
        body = goods_config_db.name
        price = float(goods_config_db.price)
    else:
        return ajax.jsonp_fail(request, message="商品信息不合法")

    wxpay_class = WxPayConfig(body=body, price=price, res_ip=ip, notify_url=notify_url, order_no=order_no,config_id=config_id)
    trade_type = "MWEB"
    res, error = wxpay_class.payExecute(trade_type)
    mweb_url = res.mweb_url if res else ""
    pay_info_add(order_no, body, 2)
    return ajax.jsonp_ok(request, {"mweb_url": mweb_url, "order_no": order_no})


def jsapi(request):
    """
      功能:微信支付——jsapi支付
      -----------------------------------------------
      添加人:王*
      -----------------------------------------------
      添加时间:2019-7-12
      -----------------------------------------------
      @api {post} /wechat/jsapi/ [微信支付]微信支付——jsapi支付
      @apiGroup area
      @apiSuccessExample {json} 成功返回
       {
              "message": "",
              "next": "",
              "data": {
                    "res":{
                    "appId": "wxd2a3750db917050e", #微信appid
                    "timeStamp": 1562911588, #时间戳
                     "nonceStr": "y0ojaCj3ymW6WQqe",#随机字符串
                     "package": "prepay_id=wx1214055577198665a4c81df31156812100", #订单详情扩展字符串
                     "signType": "MD5",  #签名方式
                     "paySign": "426EA96CE9472BD9F43B5D6956546868"  #签名
                    }
              },
              "response": "ok",
              "error": ""
          }
      @apiSuccess {str} appId      微信appid
      @apiSuccess {str} timeStamp       时间戳
      @apiSuccess {str} nonceStr    随机字符串
      @apiSuccess {str} package           订单详情扩展字符串
      @apiSuccess {str} signType           签名方式
      @apiSuccess {str} paySign           签名
      @apiErrorExample {json} 失败返回
          {
              "message": "缺少参数",
              "next": "",
              "data": {},
              "response": "fail",
              "error": ""
          }
      """
    args = request.QUERY.casts(config_id=int,goods_id=int,code=str)
    config_id = args.config_id
    goods_id = args.goods_id
    code = args.code
    if not code:
        wxpay_class = WxPayConfig(config_id=config_id)
        code_url = wxpay_class.create_url_for_code(settings.CMS_VUE_URL)
        # return HttpResponseRedirect(code_url)
        return ajax.jsonp_ok(request, {"code_url": code_url})
    if not config_id or not goods_id:
        return ajax.jsonp_fail(request, message="支付参数不合法")
    goods_config_db = get_goods_config(config_id,goods_id)
    if goods_config_db:
        body = goods_config_db.name
        price = float(goods_config_db.price)
    else:
        return ajax.jsonp_fail(request, message="商品信息不合法")

    ip = get_client_ip(request).split(",")[0]
    order_no = WxPayConfig.create_trade_no()
    wxpay_class = WxPayConfig(body=body, price=price, res_ip=ip, notify_url=notify_url, order_no=order_no, code=code,config_id=config_id)
    res, error = wxpay_class.payExecute("JSAPI")
    if res:
        pay_info_add(order_no, body, 3)
        return ajax.jsonp_ok(request, {"res": res})
    return ajax.jsonp_fail(request, {"res": {}}, message=error)


def get_client_ip(request):
    """
    获取客户端id
    :param request:
    :return:
    """
    remote_ip = request.META.get('HTTP_REMOTEIP')
    if remote_ip and remote_ip != 'unknown':
        return remote_ip
    clent_ip = request.META.get('HTTP_CLIENT_IP')
    if clent_ip and clent_ip != 'unknown':
        return clent_ip
    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
    if x_forwarded_for and x_forwarded_for != 'unknown':
        return x_forwarded_for
    remote_addr = request.META.get('REMOTE_ADDR')
    if remote_addr and remote_addr != 'unknown':
        return remote_addr
    return ''


def notify(request):
    """
    微信支付完毕异步通知
    在这个接口，调用第三方查询订单接口，获取支付状态，入库
    url:/wechat/notify/
    """
    body = request.body
    # print("______________body")
    # print(body)
    # body=b'<xml><appid><![CDATA[wxd2a3750db917050e]]></appid>\n<bank_type><![CDATA[CFT]]></bank_type>\n<cash_fee><![CDATA[1]]></cash_fee>\n<fee_type><![CDATA[CNY]]></fee_type>\n<is_subscribe><![CDATA[N]]></is_subscribe>\n<mch_id><![CDATA[1296250101]]></mch_id>\n<nonce_str><![CDATA[5981]]></nonce_str>\n<openid><![CDATA[oJvIws_CcSFl4znxeEhRTouaqBsA]]></openid>\n<out_trade_no><![CDATA[20190719112143030]]></out_trade_no>\n<result_code><![CDATA[SUCCESS]]></result_code>\n<return_code><![CDATA[SUCCESS]]></return_code>\n<sign><![CDATA[338F0237D0280BABD6C608586A875DFC]]></sign>\n<time_end><![CDATA[20190719112201]]></time_end>\n<total_fee>1</total_fee>\n<trade_type><![CDATA[NATIVE]]></trade_type>\n<transaction_id><![CDATA[4200000347201907190055469068]]></transaction_id>\n</xml>'
    # body=b'<xml><appid><![CDATA[wxd2a3750db917050e]]></appid>\n<bank_type><![CDATA[CFT]]></bank_type>\n<cash_fee><![CDATA[1]]></cash_fee>\n<fee_type><![CDATA[CNY]]></fee_type>\n<is_subscribe><![CDATA[N]]></is_subscribe>\n<mch_id><![CDATA[1296250101]]></mch_id>\n<nonce_str><![CDATA[6461]]></nonce_str>\n<openid><![CDATA[oJvIws_CcSFl4znxeEhRTouaqBsA]]></openid>\n<out_trade_no><![CDATA[20190710183239465]]></out_trade_no>\n<result_code><![CDATA[SUCCESS]]></result_code>\n<return_code><![CDATA[SUCCESS]]></return_code>\n<sign><![CDATA[FB871FA88B944023C357086B761C8AB6]]></sign>\n<time_end><![CDATA[20190710183259]]></time_end>\n<total_fee>1</total_fee>\n<trade_type><![CDATA[NATIVE]]></trade_type>\n<transaction_id><![CDATA[4200000350201907109735055115]]></transaction_id>\n</xml>'
    content = xmltodict.parse(body, encoding='utf-8').get("xml")
    mch_id = content.get("mch_id", ""),
    pay_config_db = db.default.pay_config_wechat.get(mch_id=mch_id)
    config_id=pay_config_db.id if pay_config_db else 0
    wxpay_class = WxPayConfig(config_id=config_id)

    is_sign = wxpay_class.check_sign(content)
    if is_sign:
        args = dict(
            appid=content.get("appid", ""),
            mch_id=content.get("mch_id", ""),
            transaction_id=content.get("transaction_id", ""),
            nonce_str=str(random.randint(0, 10000))

        )
        args["sign"] = wxpay_class.create_sign(args)
        url = wxpay_class.gateway + "orderquery"
        r = requests.post(url, data=wxpay_class.trans_dict_to_xml(args).encode())
        pay_data = wxpay_class.result(r)
        if pay_data.data:
            data = pay_data.data
            time_end = data.time_end  # 支付完成时间
            out_trade_no = data.out_trade_no
            pay_info_db = db.default.pay_info.get(tbkt_pay_no=out_trade_no)
            if pay_info_db:
                db.default.pay_info.filter(tbkt_pay_no=out_trade_no, ).update(
                    third_pay_no=data.transaction_id,
                    price=int(data.total_fee) / 100 if data.total_fee else 0,
                    pay_time=int(time.mktime(time.strptime(time_end, "%Y%m%d%H%M%S"))),
                    pay_state=1 if data.trade_state == "SUCCESS" else 2,
                )
            if data.trade_state == "SUCCESS":
                resp = HttpResponse(wxpay_class.trans_dict_to_xml({'return_code': 'SUCCESS', 'return_msg': 'OK'}))
                return resp
    resp = HttpResponse(wxpay_class.trans_dict_to_xml({'return_code': 'FAIL', 'return_msg': 'error'}))
    return resp


def pay_info_add(order_no, goods_name, pay_type):
    """
    微信支付时，还没有支付，进入支付页面的时候，在库里存入商品名称，支付我方编码等
    :param order_no: 我们的支付号码
    :param goods_name: 商品名称
    :param pay_type: 支付类型
    :return:
    """
    pay_info_db = db.default.pay_info.get(tbkt_pay_no=order_no)
    if not pay_info_db:
        db.default.pay_info.create(
            tbkt_pay_no=order_no,
            goods_name=goods_name,
            pay_state=0,
            pay_type=pay_type,
            add_time=int(time.time())
        )





def get_goods_config(config_id,goods_id):
    """
    微信支付配置信息返回
    :param request:
    :return:
    """
    pay_goods_db = db.default.pay_goods_wechat.get(id=goods_id,config_id=config_id)
    return pay_goods_db


